﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Text.RegularExpressions;

namespace aspnet_test_lib
{
    public class AspHiddenField
    {
        public const string VIEWSTATE = "__VIEWSTATE";
        public const string EVENTVALIDATION = "__EVENTVALIDATION";
        public const string EVENTTARGET = "__EVENTTARGET";
        public const string EVENTARGUMENT = "__EVENTARGUMENT";
    }

    public static class WebClientEx
    {
        public static string HttpPost(this WebClient webClient, string URI, string Parameters)
        {
            WebRequest req = System.Net.WebRequest.Create(URI);
            //Add these, as we're doing a POST
            req.ContentType = "application/x-www-form-urlencoded";
            req.Method = "POST";
            //We need to count how many bytes we're sending. Post'ed Faked Forms should be name=value&
            byte[] bytes = System.Text.Encoding.ASCII.GetBytes(Parameters);
            req.ContentLength = bytes.Length;
            System.IO.Stream os = req.GetRequestStream();
            os.Write(bytes, 0, bytes.Length); //Push it out there
            os.Close();
            System.Net.WebResponse resp = req.GetResponse();
            if (resp == null) return null;
            System.IO.StreamReader sr = new System.IO.StreamReader(resp.GetResponseStream());
            return sr.ReadToEnd().Trim();
        }
    }

    public class AspNetTestBrowser
    {
        private WebClient _webClient = new WebClient();
        public WebClient WebClient
        {
            get { return _webClient; }
        }

        private string _pageHtml = string.Empty;
        public string PageHtml
        {
            get { return _pageHtml; }
            private set { _pageHtml = value; }
        }

        private string _urlLocation = string.Empty;
        public string UrlLocation
        {
            get { return _urlLocation; }
            private set { _urlLocation = value; }
        }

        public string Open(string address)
        {
            this.UrlLocation = address;
            PageHtml = WebClient.DownloadString(address);

            return PageHtml;
        }

        public string Postback(string address, IDictionary<string, string> parms)
        {
            
            parms.Add(AspHiddenField.VIEWSTATE, GetAspHiddenField(this.PageHtml, AspHiddenField.VIEWSTATE));
            string eventValidation = GetAspHiddenField(this.PageHtml, AspHiddenField.EVENTVALIDATION);
            if (eventValidation != null)
            {
                parms.Add(AspHiddenField.EVENTVALIDATION, GetAspHiddenField(this.PageHtml, AspHiddenField.EVENTVALIDATION));
            }


            string urlParameters = string.Empty;
            foreach (var parm in parms)
            {
                if (!string.IsNullOrEmpty(parm.Value))
                {
                    urlParameters += string.Format("{0}={1}", parm.Key, parm.Value);
                    urlParameters += "&";
                }
            }
            if (urlParameters.EndsWith("&"))
            {
                urlParameters = urlParameters.Remove(urlParameters.Length - 1, 1);
            }

            this.PageHtml = this.WebClient.HttpPost(address, urlParameters);

            return this.PageHtml;
        }

        public string Postback(string address, string parms)
        {
            this.PageHtml =  this.WebClient.HttpPost(address, parms);
            return this.PageHtml;
        }

        public string Postback(IDictionary<string, string> parms)
        {
            return this.Postback(this.UrlLocation, parms);
        }

        private string GetAspHiddenField(string pageHtml, string hiddenField)
        {
            string pattern = string.Format("<input type=\"hidden\" name=\"{0}\" id=\"{0}\" value=\"(?<hiddenFieldValue>.*)\" />",
                hiddenField);
            Regex regex = new Regex(pattern);
            var match = regex.Match(pageHtml);

            if (match.Groups["hiddenFieldValue"].Success)
            {
                return match.Groups["hiddenFieldValue"].Value;
            }
            else
            {
                return null;
            }
        }
    }
}
